package com.bert.config;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.bert.entity.NacosConfigInfo;
import com.bert.entity.NacosDiscoveryInfo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.CachingRouteLocator;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.loadbalancer.cache.DefaultLoadBalancerCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.Executor;

@Slf4j
@Component("org.springframework.cloud.loadbalancer.cache.DefaultLoadBalancerCacheManager")
public class NacosListenConfig {

    @Value("${spring.cloud.nacos.config.file-name}")
    private String listenConfigFile;

    @Value("${spring.cloud.nacos.discovery.listen}")
    private List<String> listenServices;

    @Resource
    private NacosConfigInfo nacosConfigInfo;
    @Resource
    private NacosDiscoveryInfo nacosDiscoveryInfo;

    @Resource
    private DefaultLoadBalancerCacheManager defaultLoadBalancerCacheManager;
    @Resource
    private RouteLocator routeLocator;

    final static String LB_CACHE_NAME = "CachingServiceInstanceListSupplierCache";

    // 监听服务，更新本地负载均衡缓存
    @Bean
    public void NacosListenUpdateCache(){
        try {
            Properties properties = nacosDiscoveryInfo.getProperties();
            NamingService naming = NamingFactory.createNamingService(properties);
            for (String server : listenServices) {
                naming.subscribe(server, event -> {
                    if (event instanceof NamingEvent) {
                        String serviceName = ((NamingEvent) event).getServiceName();
                        // 缓存更新
                        Objects.requireNonNull(defaultLoadBalancerCacheManager.getCache(LB_CACHE_NAME)).evict(serviceName);
                        log.info("NacosListen Service Update Cache: " + serviceName);
                        log.info("NacosListen Instances: " + ((NamingEvent) event).getInstances());
                    }
                });
            }

        } catch (NacosException e) {
            throw new RuntimeException(e);
        }

    }

    // 监听配置，更新本地路由缓存
    @Bean
    public void NacosListenUpdateRoute(){
        try {
            Properties properties = nacosConfigInfo.getProperties();
            properties.put("dataId", listenConfigFile);
            ConfigService configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig(listenConfigFile, nacosConfigInfo.getGroup(), 5000);
            System.out.println(content);
            configService.addListener(listenConfigFile, nacosConfigInfo.getGroup(), new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    // 路由更新
                    CachingRouteLocator cachingRouteLocator = (CachingRouteLocator) routeLocator;
                    cachingRouteLocator.refresh();
                    log.info("NacosListen Service Update RouteCache: ");
                }
            });
        } catch (NacosException e) {
            throw new RuntimeException(e);
        }


    }

}
